package com.ruoyi.system.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.ruoyi.common.constant.CacheNames;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.redis.CacheUtils;
import com.ruoyi.common.utils.redis.RedisUtils;
import com.ruoyi.oss.constant.OssConstant;
import com.ruoyi.system.domain.SysOssConfig;
import com.ruoyi.system.domain.SysOssConfigFetcher;
import com.ruoyi.system.domain.SysOssConfigTable;
import com.ruoyi.system.domain.dto.*;
import com.ruoyi.system.service.ISysOssConfigService;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.babyfish.jimmer.Page;
import org.babyfish.jimmer.sql.JSqlClient;
import org.babyfish.jimmer.sql.ast.mutation.SaveMode;
import org.babyfish.jimmer.sql.ast.mutation.SimpleSaveResult;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collection;
import java.util.List;

/**
 * 对象存储配置Service业务层处理
 *
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class SysOssConfigServiceImpl implements ISysOssConfigService {

    private final JSqlClient sqlClient;

    /**
     * 项目启动时，初始化参数到缓存，加载配置类
     */
    @Override
    @PostConstruct
    public void init() {
        SysOssConfigTable table = SysOssConfigTable.$;
        List<SysOssConfigCache> list = sqlClient.createQuery(table)
                .select(table.fetch(
                        SysOssConfigCache.class
                ))
                .execute();
        // 加载OSS初始化配置
        for (SysOssConfigCache config : list) {
            String configKey = config.getConfigKey();
            if ("0".equals(config.getStatus())) {
                RedisUtils.setCacheObject(OssConstant.DEFAULT_CONFIG_KEY, configKey);
            }
            CacheUtils.put(CacheNames.SYS_OSS_CONFIG, configKey, JSONUtil.toJsonStr(config));
        }
    }

    @Override
    public SysOssConfigView queryById(String ossConfigId) {
        return sqlClient.findById(SysOssConfigView.class, ossConfigId);
    }


    @Override
    public Page<SysOssConfigView> queryPageList(SysOssConfigListInput bo, PageQuery pageQuery) {
        SysOssConfigTable table = SysOssConfigTable.$;
        return sqlClient.createQuery(table)
                .where(
                        table.configKey().eqIf(bo.getConfigKey()),
                        table.bucketName().ilikeIf(bo.getBucketName()),
                        table.status().eqIf(bo.getStatus())
                )
                .select(table.fetch(SysOssConfigView.class))
                .fetchPage(pageQuery.getPageNum(), pageQuery.getPageSize());
    }


    @Override
    public Boolean insertByBo(SysOssConfigSaveInput bo) {
        SysOssConfig config = bo.toEntity();
        if (!checkConfigKeyUnique(null,bo.getConfigKey())) {
            throw new ServiceException("操作配置'" + bo.getConfigKey() + "'失败, 配置key已存在!");
        }
        SimpleSaveResult.View<SysOssConfig, SysOssConfigView> execute = sqlClient.saveCommand(config)
                .setMode(SaveMode.INSERT_ONLY)
                .execute(SysOssConfigView.class);
        boolean flag = execute.getTotalAffectedRowCount() > 0;
        if (flag) {
            CacheUtils.put(CacheNames.SYS_OSS_CONFIG, config.configKey(), JSONUtil.toJsonStr(execute.getModifiedView()));
        }
        return flag;
    }

    @Override
    public Boolean updateByBo(SysOssConfigUpdateInput bo) {
        SysOssConfig config = bo.toEntity();
        if (!checkConfigKeyUnique(bo.getOssConfigId(),bo.getConfigKey())) {
            throw new ServiceException("操作配置'" + bo.getConfigKey() + "'失败, 配置key已存在!");
        }
        SimpleSaveResult.View<SysOssConfig, SysOssConfigView> execute = sqlClient.saveCommand(config)
                .setMode(SaveMode.UPDATE_ONLY)
                .execute(SysOssConfigView.class);
        boolean flag = execute.getTotalAffectedRowCount() > 0;
        if (flag) {
            SysOssConfigView modifiedView = execute.getModifiedView();
            CacheUtils.put(CacheNames.SYS_OSS_CONFIG, modifiedView.getConfigKey(), JSONUtil.toJsonStr(modifiedView));
        }
        return flag;
    }

    public boolean checkConfigKeyUnique(String configId, String configKey) {
        SysOssConfigTable table = SysOssConfigTable.$;
        SysOssConfig info = sqlClient.createQuery(table).where(table.configKey().eq(configKey))
                .select(table.fetch(SysOssConfigFetcher.$.allScalarFields())).fetchOneOrNull();
        if (StringUtils.isNotNull(info) && !ObjectUtil.equals(info.ossConfigId(),configId)) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    @Override
    public Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid) {
        if (isValid) {
            if (CollUtil.containsAny(ids, OssConstant.SYSTEM_DATA_IDS)) {
                throw new ServiceException("系统内置, 不可删除!");
            }
        }
        List<SysOssConfigView> list = CollUtil.newArrayList();
        for (String configId : ids) {
            SysOssConfigView config = sqlClient.findById(SysOssConfigView.class, configId);
            list.add(config);
        }

        boolean flag = sqlClient.deleteByIds(SysOssConfig.class, ids)
                .getTotalAffectedRowCount() > 0;
        if (flag) {
            list.forEach(sysOssConfig ->
                    CacheUtils.evict(CacheNames.SYS_OSS_CONFIG, sysOssConfig.getConfigKey()));
        }
        return flag;
    }

    /**
     * 启用禁用状态
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateOssConfigStatus(SysOssConfigStatusInput bo) {
        SysOssConfig sysOssConfig = bo.toEntity();
        SysOssConfigTable table = SysOssConfigTable.$;
        Integer row = sqlClient.createUpdate(table)
                .set(table.status(), "1")
                .execute();
        row += sqlClient.saveCommand(sysOssConfig)
                .setMode(SaveMode.UPDATE_ONLY)
                .execute()
                .getTotalAffectedRowCount();
        if (row > 0) {
            RedisUtils.setCacheObject(OssConstant.DEFAULT_CONFIG_KEY, sysOssConfig.configKey());
        }
        return row;
    }
}

